﻿using System;
using System.IO;
using UtilZ.Dotnet.Ex.Base;

namespace UtilZ.Dotnet.Ex.Communication.Base
{
    /// <summary>
    /// 传输数据分包器接口
    /// </summary>
    public interface IUnpacker : IDisposableZ
    {
        /// <summary>
        /// 拆分完成的数据包输出事件
        /// </summary>
        event EventHandler<DataOutputArgs> PackOutput;

        /// <summary>
        /// 对数据进行拆包
        /// </summary>
        /// <param name="unpackerPara">分包参数</param>
        /// <returns>拆包成功的数据长度</returns>
        int UnPackge(IUnpackerPara unpackerPara);
    }

    /// <summary>
    /// 网络传输数据拆包基类
    /// </summary>
    public abstract class UnpackerAbs : IUnpacker
    {
        /// <summary>
        /// 构造函数
        /// </summary>
        public UnpackerAbs()
        {

        }


        /// <summary>
        /// 包输出事件
        /// </summary>
        public event EventHandler<DataOutputArgs> PackOutput;

        /// <summary>
        /// 触发包输出事件
        /// </summary>
        /// <param name="client">接收到数据的Client</param>
        /// <param name="args">参数</param>
        protected virtual void OnRaiseOnReceivedData(IClient client, DataOutputArgs args)
        {
            var handler = this.PackOutput;
            if (handler != null)
            {
                handler(client, args);
            }
        }


        /// <summary>
        /// 对数据进行拆包
        /// </summary>
        /// <param name="unpackerPara">分包参数</param>
        /// <returns>拆包成功的数据长度</returns>
        public int UnPackge(IUnpackerPara unpackerPara)
        {
            return this.PrimitiveUnPackge(unpackerPara);
        }

        /// <summary>
        /// 对数据进行拆包
        /// </summary>
        /// <param name="unpackerPara">分包参数</param>
        /// <returns>拆包成功的数据长度</returns>
        protected abstract int PrimitiveUnPackge(IUnpackerPara unpackerPara);



        #region IDisposable
        /// <summary>
        /// 获取当前对象是否已释放[true:已释放;false:未释放]
        /// </summary>
        public bool Disposed
        {
            get
            {
                return _disposed;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        protected bool _disposed = false;
        /// <summary>
        /// Dispose
        /// </summary>
        public void Dispose()
        {
            if (this._disposed)
            {
                return;
            }
            this._disposed = true;

            this.Dispose(true);
        }

        /// <summary>
        /// Dispose
        /// </summary>
        /// <param name="disposing">标识[true:释放;false:重复释放]</param>
        protected virtual void Dispose(bool disposing)
        {

        }
        #endregion
    }

    /// <summary>
    /// 忽略数据分包器
    /// </summary>
    public class IgnoreDataUnpacker : UnpackerAbs
    {
        /// <summary>
        /// 构造函数
        /// </summary>
        public IgnoreDataUnpacker()
        {

        }

        /// <summary>
        /// 对数据进行拆包
        /// </summary>
        /// <param name="unpackerPara">分包参数</param>
        /// <returns>拆包成功的数据长度</returns>
        protected override int PrimitiveUnPackge(IUnpackerPara unpackerPara)
        {
            return unpackerPara.DataLength;
        }
    }


    /// <summary>
    /// 分包参数基类
    /// </summary>
    public interface IUnpackerPara
    {
        /// <summary>
        /// 接收到数据的Client
        /// </summary>
        IClient Client { get; }

        /// <summary>
        /// 连接信息
        /// </summary>
        LinkInfoAbs LinkInfo { get; }

        /// <summary>
        /// 用于拆包的数据Buffer
        /// </summary>
        byte[] Buffer { get; }

        /// <summary>
        /// 可拆包数据起始位置
        /// </summary>
        int Offset { get; }

        /// <summary>
        /// 可拆包数据总长度
        /// </summary>
        int DataLength { get; }

        /// <summary>
        /// 本次接收到数据包长度
        /// </summary>
        int ReceiveLength { get; }

        /// <summary>
        /// 数据读取器
        /// </summary>
        BinaryReader Reader { get; }
    }


    /// <summary>
    /// 分包参数基类
    /// </summary>
    public abstract class UnpackerParaAbs : IUnpackerPara
    {
        /// <summary>
        /// 接收到数据的Client
        /// </summary>
        public IClient Client { get; set; }

        /// <summary>
        /// 连接信息
        /// </summary>
        public LinkInfoAbs LinkInfo { get; set; }

        /// <summary>
        /// 用于拆包的数据Buffer
        /// </summary>
        public byte[] Buffer { get; set; }

        /// <summary>
        /// 可拆包数据起始位置
        /// </summary>
        public int Offset { get; set; }

        /// <summary>
        /// 可拆包数据总长度
        /// </summary>
        public int DataLength { get; set; }

        /// <summary>
        /// 本次接收到数据包长度
        /// </summary>
        public int ReceiveLength { get; set; }

        /// <summary>
        /// 数据读取器
        /// </summary>
        public BinaryReader Reader { get; set; }

        /// <summary>
        /// 构造函数
        /// </summary>
        public UnpackerParaAbs()
        {

        }
    }


    /// <summary>
    /// 分包器使用模式
    /// </summary>
    public enum UnpackerUseMode
    {
        /// <summary>
        /// 一个Client独占  
        /// </summary>
        Monopolize,

        /// <summary>
        /// 多个Client共享
        /// </summary>
        Share,
    }


    /// <summary>
    /// 分包器数据输出模式
    /// </summary>
    public enum UnpackerDataOuputMode
    {
        /// <summary>
        /// 含包头
        /// </summary>
        HasHead,

        /// <summary>
        /// 无包头
        /// </summary>
        NoHead,
    }

}
